import { defineComponent, provide, getCurrentInstance, toRef, Ref, InjectionKey, PropType } from 'vue'
import { getSlot } from '../_util/props-util'
import { useMemo } from '../_util/hooks'
import { mapOptions, WillOption } from '../_util/normalizeOptions'
import Checkbox from './Checkbox'

export type CheckboxGroupContextProps = {
  disabledRef: Ref<boolean>
  nameRef: Ref<string>
  valueRef: Ref<Array<string | number>>
  toggleOption: (opt: object) => void
}

export const checkboxGroupContext: InjectionKey<CheckboxGroupContextProps> = Symbol('checkboxGroupContext')

const prefixCls = 'x-checkbox-group'

export default defineComponent({
  name: prefixCls,
  props: {
    name: String,
    options: Array as PropType<WillOption[]>,
    value: Array as PropType<(string | number)[]>,
    vertical: Boolean,
    disabled: Boolean
  },
  emits: ['update:value', 'change'],
  setup(props, { emit }) {
    const { proxy: vm } = getCurrentInstance()

    const val = useMemo(() => props.value)

    function toggleOption(opt) {
      const value = [...val.value]
      const i = value.indexOf(opt.value)
      if (i > -1) {
        value.splice(i, 1)
      } else {
        value.push(opt.value)
      }
      emit('update:value', value)
      emit('change', value)
    }

    // ========================== Provide ==========================
    provide(checkboxGroupContext, {
      disabledRef: toRef(props, 'disabled'),
      nameRef: toRef(props, 'name'),
      valueRef: toRef(val, 'value'),
      toggleOption
    })

    return () => {
      let children
      if (props.options?.length) {
        children = mapOptions(props.options, opt => (
          <Checkbox key={opt.value} checked={val.value.indexOf(opt.value) != -1} name={props.name} value={opt.value} disabled={opt.disabled || props.disabled} style={opt.style}>
            {opt.label}
          </Checkbox>
        ))
      } else {
        children = getSlot(vm)
      }

      const cls = [prefixCls, props.vertical && `${prefixCls}-vertical`]

      return <div class={cls}>{children}</div>
    }
  }
})
